package eclipse.client;

import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import com.sun.opengl.util.texture.*;
import eclipse.*;
import eclipse.client.threadpool.*;
import eclipse.client.forms.*;
import eclipse.lib.*;
import eclipse.lib.graphics.*;
import eclipse.lib.sound.*;
import eclipse.lib.sockets.*;
import eclipse.util.*;
import eclipse.util.io.*;
/**
 * The Loader class loads all the data that the Client will potentially used.
 * This is called at the start of either the Application or the Applet.
 */
public class Loader
{
	private JPanel loaderSurface;
	private JProgressBar loaderBar;
	private LoaderThread loaderThread;
	/**
	 * returns the Container object for the JPanel associated with the status bar.
	 * @return
	 */
	public Container getSurface()
	{
		return loaderSurface;
	}	
	/**
	 * Initializes the loader Object. 
	 * This object then loads all the data used in the Database class.	 
	 */
	public Loader()
	{
		loaderSurface 	= new JPanel();
		loaderBar		= new JProgressBar(0, 100);
		loaderThread 	= new LoaderThread();
		loaderBar.setStringPainted(true);
		loaderSurface.add(loaderBar);				
		//System.out.println("Loading INI..."); 		Loader.INIInit();
		//System.out.println("Loading TCP..."); 		Loader.TCPInit(0);
		//System.out.println("Loading Threads..."); 	Loader.ThreadInit();
		//System.out.println("Loading GUI..."); 		Loader.GUIInit();	
	}	
	/**
	 * Initializes all the threads.
	 *
	 */
	public void ThreadInit()
	{	
		int val = loaderBar.getValue();
		loaderBar.setString("Loading Threads...");
		PropertyFile pFile = new PropertyFile(new ERL("jar://config").openStream());
		String menuMusic = pFile.readProperty("MAINMENU", "MUSIC");
		Database.audioChannel = new AudioDevice();
		
		for(int i = 0; i < 10; i++)
			loaderBar.setValue(val + i);
		
		if(menuMusic.trim().length() != 0)
		{
			Database.audioChannel.loadAudio(menuMusic);
			Database.audioChannel.loopAudio();
		}
		Database.threadCache = new ThreadCache();
		
		for(int i = 10; i < 20; i++)
			loaderBar.setValue(val + i);
	}
	/**
	 * Loads the tcp connection. 
	 * @param serverIndex represents the server the client will attempt to connect to.
	 */
	public void TCPInit(int serverIndex)	
	{
		int val = loaderBar.getValue();
		loaderBar.setString("Loading TCP...");
		Database.Socket = null;
		Database.Socket = new ClientSocket
		(
			Database.SERVERIP.get(serverIndex),
			Integer.parseInt(Database.SERVERPORT.get(serverIndex).toString())
		);
		for(int i = 0; i < 20; i++)
			loaderBar.setValue(val + i);		
	}
	/**
	 * Loads the game's Database from the config file.
	 *
	 */
	public void INIInit()
	{
		int val = loaderBar.getValue();
		loaderBar.setString("Loading INI...");
		PropertyFile pData = new PropertyFile(new ERL("jar://config").openStream());
		
		Database.TILEDATABASE = pData.readProperty("ENGINE", "DATABASE", "TILEDIR");
		Database.SPRITEDATABASE = pData.readProperty("ENGINE", "DATABASE", "SPRITEDIR");
		Database.MAXSERVERS = Integer.parseInt(pData.readProperty("SERVERCOUNT"));
		Database.SERVERIP 	= new ArrayList	<String>	(Database.MAXSERVERS);
		Database.SERVERPORT = new ArrayList	<Object>	(Database.MAXSERVERS);
		Database.SERVERNAME = new ArrayList <String>	(Database.MAXSERVERS);
		loaderBar.setValue(++val);
		for(int i = 0; i < Database.MAXSERVERS; i++)
		{
			Database.SERVERIP.add(		
					pData.readProperty("SERVER" + i, "IP"));
			Database.SERVERPORT.add(
					Integer.parseInt(
						pData.readProperty("SERVER" + i, "PORT")));
			Database.SERVERNAME.add(
					pData.readProperty("SERVER" + i, "NAME"));
		}
		loaderBar.setValue(++val);
		Database.IMGMAINMENU	= pData.readProperty("MAINMENU", "GUI");
		Database.IMGLOGIN		= pData.readProperty("LOGIN", "GUI");
		Database.IMGCHARSELECT	= pData.readProperty("CHARSELECT", "GUI");
		Database.IMGNEWACCOUNT	= pData.readProperty("NEWACCOUNT", "GUI");
		Database.IMGMIRAGEMENU	= pData.readProperty("MIRAGE", "MINIMENU", "GUI");
		loaderBar.setValue(++val);
		loaderBar.setValue(++val);
		Database.MAINMENUEXITX = Integer.parseInt(pData.readProperty("MAINMENU", "EXIT", "X"));
		Database.MAINMENUEXITW = Integer.parseInt(pData.readProperty("MAINMENU", "EXIT", "W"));
		Database.MAINMENUEXITY = Integer.parseInt(pData.readProperty("MAINMENU", "EXIT", "Y"));
		Database.MAINMENUEXITH = Integer.parseInt(pData.readProperty("MAINMENU", "EXIT", "H"));
		loaderBar.setValue(++val);
		Database.MAINMENULOGINX = Integer.parseInt(pData.readProperty("MAINMENU", "LOGIN", "X"));
		Database.MAINMENULOGINY = Integer.parseInt(pData.readProperty("MAINMENU", "LOGIN", "Y"));
		Database.MAINMENULOGINW = Integer.parseInt(pData.readProperty("MAINMENU", "LOGIN", "W"));
		Database.MAINMENULOGINH = Integer.parseInt(pData.readProperty("MAINMENU", "LOGIN", "H"));
		loaderBar.setValue(++val);
		Database.MAINMENUNEWACCOUNTX = Integer.parseInt(pData.readProperty("MAINMENU", "NEWACCOUNT", "X"));
		Database.MAINMENUNEWACCOUNTY = Integer.parseInt(pData.readProperty("MAINMENU", "NEWACCOUNT", "Y"));
		Database.MAINMENUNEWACCOUNTH = Integer.parseInt(pData.readProperty("MAINMENU", "NEWACCOUNT", "H"));
		Database.MAINMENUNEWACCOUNTW = Integer.parseInt(pData.readProperty("MAINMENU", "NEWACCOUNT", "W"));
		loaderBar.setValue(++val);		
		loaderBar.setValue(++val);				
		loaderBar.setValue(++val);
		loaderBar.setValue(++val);
		Database.LOGINEXITX = Integer.parseInt(pData.readProperty("LOGIN", "EXIT", "X"));
		Database.LOGINEXITY = Integer.parseInt(pData.readProperty("LOGIN", "EXIT", "Y"));
		Database.LOGINEXITW = Integer.parseInt(pData.readProperty("LOGIN", "EXIT", "W"));
		Database.LOGINEXITH = Integer.parseInt(pData.readProperty("LOGIN", "EXIT", "H"));
		loaderBar.setValue(++val);
		Database.LOGINLOGINX = Integer.parseInt(pData.readProperty("LOGIN", "LOGIN", "X"));
		Database.LOGINLOGINY = Integer.parseInt(pData.readProperty("LOGIN", "LOGIN", "Y"));
		Database.LOGINLOGINW = Integer.parseInt(pData.readProperty("LOGIN", "LOGIN", "W"));
		Database.LOGINLOGINH = Integer.parseInt(pData.readProperty("LOGIN", "LOGIN", "H"));
		loaderBar.setValue(++val);		
		loaderBar.setValue(++val);		
		loaderBar.setValue(++val);		
		loaderBar.setValue(++val);		
		Database.NEWACCOUNTCONFH	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "CONF", "H"));
		Database.NEWACCOUNTCONFW	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "CONF", "W"));
		Database.NEWACCOUNTCONFX	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "CONF", "X"));
		Database.NEWACCOUNTCONFY	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "CONF", "Y"));
		Database.NEWACCOUNTEXITH	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "EXIT", "H"));
		Database.NEWACCOUNTEXITW	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "EXIT", "W"));
		Database.NEWACCOUNTEXITX	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "EXIT", "X"));
		Database.NEWACCOUNTEXITY	= Integer.parseInt(pData.readProperty("NEWACCOUNT", "INPUT", "EXIT", "Y"));
		Database.MAX_SPRITESETS		= Integer.parseInt(pData.readProperty("SPRITESET", "COUNT"));
		Database.MAX_TILESETS		= Integer.parseInt(pData.readProperty("TILESET", "COUNT"));
		Database.tTileSheet 		= new Texture[Database.MAX_TILESETS];
		Database.tSpriteSheet		= new Texture[Database.MAX_SPRITESETS];
		Database.ID_LAYER			= new int[10];
		Database.MAX_MAPS 			= Integer.parseInt(pData.readProperty("MAPS", "COUNT"));
		loaderBar.setValue(++val);
		if(pData.readProperty("ENGINE", "RES").contains("H"))
			Database.HIGH_RES = true;
		else
			Database.HIGH_RES = false;
		if(Integer.parseInt(pData.readProperty("ENGINE", "DIM")) == 3)
			Database.RENDER_AS_3D = true;
		else
			Database.RENDER_AS_3D = false;
		String lag = pData.readProperty("ENGINE", "LATENCY");
		if(lag.equals("EXTRALOW"))
			Database.lag = LATENCY.EXTRALOW;
		else if(lag.equals("LOW"))
			Database.lag = LATENCY.LOW;
		else if(lag.equals("MEDIUM"))
			Database.lag = LATENCY.MEDIUM;
		else if(lag.equals("HIGH"))
			Database.lag = LATENCY.HIGH;
		else
			Database.lag = LATENCY.EXTRAHIGH;
		Database.FPS				= Integer.parseInt(pData.readProperty("ENGINE", "FPS")) + 1;		
		pData.closeProperty();
		loaderBar.setValue(++val);loaderBar.setValue(++val);loaderBar.setValue(++val);
	}
	/**
	 * Initializes the graphics and OpenGL object.
	 *
	 */
	public void GUIInit()
	{		
		int val = loaderBar.getValue();
		loaderBar.setString("Loading Graphics...");
		GLRenderer glObject = new GLRenderer();
		val += 10;
		loaderBar.setValue(val);
		try
		{
			loaderBar.setString("Loading OpenGL...");
			ServerList.makeGUI();		
			if(!Database.APPLET)
			{
				Database.Mirage		 = new StandardForm(Constants.ENGINE, 640, 480, 200, 200);				
				Database.drawSurface = Database.Mirage;				
			}
			Database.glInterface = new GLInterface(Database.drawSurface, glObject);										
			val += 10;
			loaderBar.setValue(val);
			loaderBar.setString("Loading Forms...");
			Database.MainMenu = new MainMenu("Main Menu", 300, 100, new ERL(Database.IMGMAINMENU));
				new MouseHandler(Database.MainMenu, Constants.MENUSTATE_MAINMENU);
			loaderBar.setValue(85);
			Database.Login = new Login("Login", 300, 100, new ERL(Database.IMGLOGIN));
				new MouseHandler(Database.Login, Constants.MENUSTATE_LOGINMENU);
			loaderBar.setValue(90);			
			loaderBar.setValue(95);
			Database.NewAccount = new NewAccount("New Account", 300, 100, new ERL(Database.IMGNEWACCOUNT));
				new MouseHandler(Database.NewAccount, Constants.MENUSTATE_NEWACCOUNTMENU);
			loaderBar.setValue(100);			
			loaderBar.setString("Executing Eclipse");			
			loaderThread.setRunStatus(false);
			while(loaderThread.isAlive())
			;			
			ServerList.showForm();			
		}
		catch(Exception e)
		{
			eclipse.ErrorManager.handleError(e);
		}
	}	
}
